@brett_lamy/docstream 1.2.2 → 1.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -1
- package/package.json +1 -1
- package/src/demo/markdown.ts +1 -1
- package/src/docs/DocsRenderer.tsx +21 -9
- package/src/gitbook/ast.ts +251 -38
- package/src/gitbook/index.ts +1 -1
- package/src/gitbook/inline.ts +901 -169
- package/src/gitbook/parse.ts +419 -170
- package/src/gitbook/serialize.ts +448 -127
- package/src/index.ts +2 -0
package/README.md
CHANGED
|
@@ -8,7 +8,11 @@ GitBook-aware markdown rendering for React applications and AI streaming surface
|
|
|
8
8
|
|
|
9
9
|
- React renderer for GitBook-style markdown blocks.
|
|
10
10
|
- Streaming-friendly `GitbookStreamdown` component inspired by `vercel/streamdown`.
|
|
11
|
-
- Parser and serializer for round-tripping supported GitBook syntax
|
|
11
|
+
- Parser and serializer for round-tripping supported GitBook syntax — byte-for-byte: `serializeMarkdown(parseMarkdown(md)) === md`
|
|
12
|
+
for Markdown and GitBook pages (the author's emphasis markers, escapes, link forms and reference definitions,
|
|
13
|
+
Markdown vs HTML images, blank lines between blocks, list markers, fences, table layout and tag lines as written).
|
|
14
|
+
Layout-only fields (`gap`, `raw`, `opening`, …) are recorded only where the source differs from the default
|
|
15
|
+
output, and are ignored once they no longer fit an edited node.
|
|
12
16
|
- Syntax-highlighted code blocks through `lowlight`.
|
|
13
17
|
- GitBook block support for hints, tabs, expandables, steppers, embeds, content refs, columns, figures, tables, math, dividers, updates, and OpenAPI operations.
|
|
14
18
|
- CSS exported as a stable package entrypoint so host apps can theme with CSS variables or shadcn-style design tokens.
|
package/package.json
CHANGED
package/src/demo/markdown.ts
CHANGED
|
@@ -177,7 +177,7 @@ function inlineDemoKeepingTag(tagLine: string, node: DemoNode, files: DemoFile[]
|
|
|
177
177
|
const next = inlineDemoNode(node, files, meta)
|
|
178
178
|
const out = serializeBlocks([next])
|
|
179
179
|
const bare = (n: DemoNode): DemoNode => {
|
|
180
|
-
const { files: _files, open: _open, ...rest } = n
|
|
180
|
+
const { files: _files, open: _open, raw: _raw, ...rest } = n
|
|
181
181
|
return rest
|
|
182
182
|
}
|
|
183
183
|
if (serializeBlocks([bare(next)]) !== serializeBlocks([bare(node)])) return out
|
|
@@ -52,8 +52,12 @@ function InlineText({ nodes }: { nodes: Inline[] }) {
|
|
|
52
52
|
return (
|
|
53
53
|
<>
|
|
54
54
|
{nodes.map((n, i) => {
|
|
55
|
-
|
|
56
|
-
|
|
55
|
+
const emphasized = !!(n.bold || n.italic || n.strike)
|
|
56
|
+
let el: ReactNode
|
|
57
|
+
if (n.type === "reference") {
|
|
58
|
+
if (!emphasized && !n.link) return <InlineReference key={i} node={n} />
|
|
59
|
+
el = <InlineReference node={n} />
|
|
60
|
+
} else if (n.type === "image") {
|
|
57
61
|
const img = (
|
|
58
62
|
<img
|
|
59
63
|
src={resolveAsset(n.src)}
|
|
@@ -62,16 +66,20 @@ function InlineText({ nodes }: { nodes: Inline[] }) {
|
|
|
62
66
|
style={{ width: n.width, height: n.height }}
|
|
63
67
|
/>
|
|
64
68
|
)
|
|
65
|
-
|
|
69
|
+
const linked = n.link ? (
|
|
66
70
|
<a key={i} href={n.link} target="_blank" rel="noreferrer" className="docs-inline-img-link">
|
|
67
71
|
{img}
|
|
68
72
|
</a>
|
|
69
|
-
) :
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
73
|
+
) : null
|
|
74
|
+
if (!emphasized) return linked ?? <span key={i}>{img}</span>
|
|
75
|
+
// The image's link is its own anchor; emphasis wraps it.
|
|
76
|
+
el = linked ?? img
|
|
77
|
+
if (n.bold) el = <strong>{el}</strong>
|
|
78
|
+
if (n.italic) el = <em>{el}</em>
|
|
79
|
+
if (n.strike) el = <s>{el}</s>
|
|
80
|
+
return <span key={i}>{el}</span>
|
|
81
|
+
} else el = n.text
|
|
82
|
+
if (n.type === "text" && n.code) el = <code>{el}</code>
|
|
75
83
|
if (n.bold) el = <strong>{el}</strong>
|
|
76
84
|
if (n.italic) el = <em>{el}</em>
|
|
77
85
|
if (n.strike) el = <s>{el}</s>
|
|
@@ -523,6 +531,10 @@ function BlockView({ block, liveRenderer, sourceRenderer }: { block: Block } & R
|
|
|
523
531
|
method={block.method || "get"}
|
|
524
532
|
/>
|
|
525
533
|
)
|
|
534
|
+
// Reference definitions and verbatim-kept tags carry no content of their own.
|
|
535
|
+
case "definition":
|
|
536
|
+
case "raw":
|
|
537
|
+
return null
|
|
526
538
|
}
|
|
527
539
|
}
|
|
528
540
|
|
package/src/gitbook/ast.ts
CHANGED
|
@@ -3,29 +3,107 @@
|
|
|
3
3
|
|
|
4
4
|
export type HintStyle = "info" | "success" | "warning" | "danger"
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Formatting every inline carries — text runs, chips and inline images alike, so emphasis and links can span
|
|
8
|
+
* them (`**ask @brett**`, `*see *`, `[](url)`) — plus how the source spelled it.
|
|
9
|
+
*/
|
|
10
|
+
export interface InlineMarks {
|
|
9
11
|
bold?: boolean
|
|
10
12
|
italic?: boolean
|
|
11
13
|
strike?: boolean
|
|
12
|
-
code?: boolean
|
|
13
14
|
link?: string
|
|
14
15
|
/**
|
|
15
16
|
* The link sits inside the emphasis (`**[x](url)**`) rather than around it
|
|
16
17
|
* (`[**x**](url)`, the default). Kept so the source round-trips byte-for-byte.
|
|
17
18
|
*/
|
|
18
19
|
linkInner?: true
|
|
20
|
+
/**
|
|
21
|
+
* How the source spelled this inline's formatting, outermost → innermost, when that differs from the default
|
|
22
|
+
* output (`_italic_`, `**bold**`, `~~strike~~`, link around its emphasis, bare autolinks). Each entry is an
|
|
23
|
+
* emphasis marker, or a link form (see {@link LinkForm}). E.g. `**_x_**` → `["**", "_"]`, `***x***` →
|
|
24
|
+
* `["*", "**"]`, `*x*` → `["*"]`, `*a *b* c*` → `["*", "*"]` for `b`.
|
|
25
|
+
*
|
|
26
|
+
* A hint only — the boolean marks and `link` stay authoritative: entries for marks the run no longer has are
|
|
27
|
+
* ignored, marks it has without an entry get the default spelling and position. Absent on runs that
|
|
28
|
+
* serialize the default way and on programmatically created nodes.
|
|
29
|
+
*/
|
|
30
|
+
delims?: InlineDelimiter[]
|
|
31
|
+
/** The link's title as written between the quotes: `[x](url "title")`. */
|
|
32
|
+
linkTitle?: string
|
|
33
|
+
/**
|
|
34
|
+
* The reference label of a reference-style link, as written: `ref` for `[text][ref]`, and the link text
|
|
35
|
+
* for the collapsed `[text][]` and shortcut `[text]` forms.
|
|
36
|
+
*/
|
|
37
|
+
linkRef?: string
|
|
38
|
+
/** The opening tag of an inline HTML link as written (`<a href="…" target="_blank">`). */
|
|
39
|
+
linkTag?: string
|
|
40
|
+
/** The closing tag of an inline HTML link, when not `</a>` (`</A>`). */
|
|
41
|
+
linkTagEnd?: string
|
|
42
|
+
/**
|
|
43
|
+
* Link identity: set on the runs of a link that directly follows another link to the same target
|
|
44
|
+
* (`[a](u)[b](u)`), so the two stay distinct instead of merging into one. Runs of one link share it.
|
|
45
|
+
*/
|
|
46
|
+
linkId?: number
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export interface TextNode extends InlineMarks {
|
|
50
|
+
type: "text"
|
|
51
|
+
text: string
|
|
52
|
+
code?: boolean
|
|
53
|
+
/**
|
|
54
|
+
* The source wrote every character of this run backslash-escaped (`snake\_case` → `snake`, `_` escaped,
|
|
55
|
+
* `case`). Only ASCII punctuation can be escaped. Kept so author escapes survive even where they aren't
|
|
56
|
+
* needed; the text itself is the literal characters.
|
|
57
|
+
*/
|
|
58
|
+
escaped?: true
|
|
59
|
+
/**
|
|
60
|
+
* Code span in a GFM table cell: offsets (in `text`) of the `|` characters the source wrote bare instead
|
|
61
|
+
* of as `\|`. Serialization escapes every other pipe.
|
|
62
|
+
*/
|
|
63
|
+
barePipes?: number[]
|
|
64
|
+
/** A code span's backtick count as written, when longer than serialization needs (```` ```x``` ````). */
|
|
65
|
+
ticks?: number
|
|
19
66
|
}
|
|
20
67
|
|
|
21
|
-
/**
|
|
22
|
-
export
|
|
68
|
+
/** An emphasis marker as written in the source. */
|
|
69
|
+
export type EmphasisDelimiter = "**" | "__" | "*" | "_" | "~~"
|
|
70
|
+
/**
|
|
71
|
+
* How a link is written: `"link"` `[x](url)`, `"<>"` `<url>`, `"url"` a bare autolink, `"ref"` `[x][label]`,
|
|
72
|
+
* `"collapsed"` `[x][]`, `"shortcut"` `[x]` (the last three resolved through a `[label]: url` definition),
|
|
73
|
+
* `"html"` `<a href="url">x</a>`.
|
|
74
|
+
*/
|
|
75
|
+
export type LinkForm = "link" | "<>" | "url" | "ref" | "collapsed" | "shortcut" | "html"
|
|
76
|
+
/** An entry of {@link InlineMarks.delims}: an emphasis marker or a link form. */
|
|
77
|
+
export type InlineDelimiter = EmphasisDelimiter | LinkForm
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Inline image: `` (`syntax: "markdown"`), or HTML `<img …>` / `<a href><img …></a>`
|
|
81
|
+
* (GitHub README badge style, the default).
|
|
82
|
+
*
|
|
83
|
+
* `link` without a link form in `delims` is the HTML `<a href>` around the `<img>`; with one
|
|
84
|
+
* (`[](url)`) it is an ordinary link mark that may span neighbouring text.
|
|
85
|
+
*/
|
|
86
|
+
export interface InlineImageNode extends InlineMarks {
|
|
23
87
|
type: "image"
|
|
24
88
|
src: string
|
|
25
89
|
alt?: string
|
|
26
90
|
width?: string
|
|
27
91
|
height?: string
|
|
28
|
-
|
|
92
|
+
/** ``'s title, as written between the quotes. */
|
|
93
|
+
title?: string
|
|
94
|
+
/** Written as Markdown ``. Absent: HTML `<img>`. */
|
|
95
|
+
syntax?: "markdown"
|
|
96
|
+
/**
|
|
97
|
+
* A Markdown image whose source comes from a definition: `![alt][label]` (`"ref"`), `![alt][]`
|
|
98
|
+
* (`"collapsed"`) or `![alt]` (`"shortcut"`), with `srcRef` the label as written.
|
|
99
|
+
*/
|
|
100
|
+
srcForm?: "ref" | "collapsed" | "shortcut"
|
|
101
|
+
srcRef?: string
|
|
102
|
+
/**
|
|
103
|
+
* The HTML as written (`<img …>`, or `<a href><img …></a>` for a linked image). Serialization reuses it
|
|
104
|
+
* while it still says the same src / alt / width / height / link; otherwise it writes fresh HTML.
|
|
105
|
+
*/
|
|
106
|
+
html?: string
|
|
29
107
|
}
|
|
30
108
|
|
|
31
109
|
export type ReferenceKind = "mention" | "tag" | "codebase" | "citation"
|
|
@@ -34,8 +112,10 @@ export type ReferenceKind = "mention" | "tag" | "codebase" | "citation"
|
|
|
34
112
|
* Inline reference chip: `@mention`, `#tag`, or footnote-style citation `[^id]`.
|
|
35
113
|
* `id` carries no sigil. Citations resolve `url`/`label` from their
|
|
36
114
|
* `[^id]: url "Label"` definition at parse time when one exists.
|
|
115
|
+
*
|
|
116
|
+
* The inherited `link` is a link *around* the chip (`[@brett](url)`); `url` is the citation's target.
|
|
37
117
|
*/
|
|
38
|
-
export interface ReferenceNode {
|
|
118
|
+
export interface ReferenceNode extends InlineMarks {
|
|
39
119
|
type: "reference"
|
|
40
120
|
kind: ReferenceKind
|
|
41
121
|
id: string
|
|
@@ -52,18 +132,55 @@ export interface CitationDef {
|
|
|
52
132
|
|
|
53
133
|
export type Inline = TextNode | InlineImageNode | ReferenceNode
|
|
54
134
|
|
|
55
|
-
|
|
135
|
+
/**
|
|
136
|
+
* Layout the source used around a block, recorded only where it differs from the serializer's default so
|
|
137
|
+
* pages round-trip byte-for-byte.
|
|
138
|
+
*/
|
|
139
|
+
export interface BlockSpacing {
|
|
140
|
+
/**
|
|
141
|
+
* Blank lines before this block (or tab / step / column / update / list item): by default 1 between
|
|
142
|
+
* siblings and 0 before the first child of a container (1 after an expandable's `<summary>`).
|
|
143
|
+
*/
|
|
144
|
+
gap?: number
|
|
145
|
+
/** Those blank lines as written, when some hold whitespace. */
|
|
146
|
+
blanks?: string[]
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/** A `{% tag %}` container's opening and closing lines as written, reused while they still say the same. */
|
|
150
|
+
export interface TagLines {
|
|
151
|
+
/** The opening tag line, when not the one serialization writes (quote style, spacing, extra attributes). */
|
|
152
|
+
opening?: string
|
|
153
|
+
/** The closing tag line, when not the canonical `{% endtag %}` ("" when the input ended first). */
|
|
154
|
+
closing?: string
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/** A block's source lines as written, where they aren't what serialization writes; reused while they still parse to the same block. */
|
|
158
|
+
export interface RawSource {
|
|
159
|
+
raw?: string
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/** Spacing inside a container, before its closing line. */
|
|
163
|
+
export interface ContainerSpacing extends BlockSpacing {
|
|
164
|
+
/** Blank lines between the last child and the closing tag (default 0; 1 in an expandable). */
|
|
165
|
+
gapEnd?: number
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
export interface ParagraphNode extends BlockSpacing {
|
|
56
169
|
type: "paragraph"
|
|
57
170
|
children: Inline[]
|
|
171
|
+
/** Whitespace before the paragraph's first line, as written (continuation lines keep theirs in the text). */
|
|
172
|
+
indent?: string
|
|
58
173
|
}
|
|
59
174
|
|
|
60
|
-
export interface HeadingNode {
|
|
175
|
+
export interface HeadingNode extends BlockSpacing {
|
|
61
176
|
type: "heading"
|
|
62
177
|
level: 1 | 2 | 3 | 4 | 5 | 6
|
|
63
178
|
children: Inline[]
|
|
179
|
+
/** A setext heading's underline as written (`===`, `---`); absent for `#` headings. */
|
|
180
|
+
setext?: string
|
|
64
181
|
}
|
|
65
182
|
|
|
66
|
-
export interface CodeBlockNode {
|
|
183
|
+
export interface CodeBlockNode extends BlockSpacing {
|
|
67
184
|
type: "code"
|
|
68
185
|
language: string | null
|
|
69
186
|
title: string | null
|
|
@@ -86,21 +203,31 @@ export interface CodeBlockNode {
|
|
|
86
203
|
collapsedCodeLines?: number
|
|
87
204
|
/** Maximum source lines visible before expanded code scrolls. */
|
|
88
205
|
expandedCodeLines?: number
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
206
|
+
/** The opening fence as written when not ```` ``` ```` (`~~~`, ````` ```` `````). */
|
|
207
|
+
fence?: string
|
|
208
|
+
/** The info string as written after the fence, when it isn't the one serialization writes. */
|
|
209
|
+
info?: string
|
|
210
|
+
/** The closing fence line as written, when it isn't the opening fence ("" when the input ended first). */
|
|
211
|
+
closingFence?: string
|
|
212
|
+
/** An indented (four-space) code block rather than a fence. */
|
|
213
|
+
indented?: true
|
|
214
|
+
/** The block as written when it isn't a plain fence (a `{% code %}` wrapper), reused while it still says the same. */
|
|
215
|
+
raw?: string
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
export interface HintNode extends ContainerSpacing, TagLines {
|
|
92
219
|
type: "hint"
|
|
93
220
|
style: HintStyle
|
|
94
221
|
children: Block[]
|
|
95
222
|
}
|
|
96
223
|
|
|
97
|
-
export interface TabNode {
|
|
224
|
+
export interface TabNode extends ContainerSpacing, TagLines {
|
|
98
225
|
type: "tab"
|
|
99
226
|
title: string
|
|
100
227
|
children: Block[]
|
|
101
228
|
}
|
|
102
229
|
|
|
103
|
-
export interface TabsNode {
|
|
230
|
+
export interface TabsNode extends ContainerSpacing, TagLines {
|
|
104
231
|
type: "tabs"
|
|
105
232
|
tabs: TabNode[]
|
|
106
233
|
/**
|
|
@@ -127,7 +254,7 @@ export type PackageManager = "npm" | "pnpm" | "yarn" | "bun"
|
|
|
127
254
|
* manager (`pnpm="…"`). The reader's manager is synced page-wide (and across
|
|
128
255
|
* pages) under `sync` — `"pm"` by default, the same key install `{% tabs %}` use.
|
|
129
256
|
*/
|
|
130
|
-
export interface CommandNode {
|
|
257
|
+
export interface CommandNode extends BlockSpacing, RawSource {
|
|
131
258
|
type: "command"
|
|
132
259
|
/** The npm / npx command (may span lines). */
|
|
133
260
|
command: string
|
|
@@ -137,24 +264,36 @@ export interface CommandNode {
|
|
|
137
264
|
sync?: string
|
|
138
265
|
}
|
|
139
266
|
|
|
140
|
-
export interface ExpandableNode {
|
|
267
|
+
export interface ExpandableNode extends ContainerSpacing {
|
|
268
|
+
/** The closing line, when not `</details>`. */
|
|
269
|
+
closing?: string
|
|
141
270
|
type: "expandable"
|
|
142
271
|
summary: string
|
|
143
272
|
children: Block[]
|
|
273
|
+
/**
|
|
274
|
+
* The lines from `<details>` through `</summary>` as written, when not `<details>`, a blank line,
|
|
275
|
+
* `<summary>…</summary>`. Reused while they still say the same summary.
|
|
276
|
+
*/
|
|
277
|
+
opening?: string
|
|
144
278
|
}
|
|
145
279
|
|
|
146
|
-
export interface StepNode {
|
|
280
|
+
export interface StepNode extends ContainerSpacing, TagLines {
|
|
147
281
|
type: "step"
|
|
148
282
|
title: string
|
|
149
283
|
children: Block[]
|
|
284
|
+
/**
|
|
285
|
+
* The title heading as written (and any blank lines before it), when not `### title` — `## Title`,
|
|
286
|
+
* `### **Bold** title`. Reused while it still gives the same title.
|
|
287
|
+
*/
|
|
288
|
+
heading?: string
|
|
150
289
|
}
|
|
151
290
|
|
|
152
|
-
export interface StepperNode {
|
|
291
|
+
export interface StepperNode extends ContainerSpacing, TagLines {
|
|
153
292
|
type: "stepper"
|
|
154
293
|
steps: StepNode[]
|
|
155
294
|
}
|
|
156
295
|
|
|
157
|
-
export interface EmbedNode {
|
|
296
|
+
export interface EmbedNode extends BlockSpacing {
|
|
158
297
|
type: "embed"
|
|
159
298
|
url: string
|
|
160
299
|
title?: string
|
|
@@ -163,12 +302,16 @@ export interface EmbedNode {
|
|
|
163
302
|
muted?: boolean
|
|
164
303
|
controls?: boolean
|
|
165
304
|
poster?: string
|
|
305
|
+
/** The tag as written (with its `{% endembed %}`), reused while it still says the same. */
|
|
306
|
+
raw?: string
|
|
166
307
|
}
|
|
167
308
|
|
|
168
|
-
export interface ContentRefNode {
|
|
309
|
+
export interface ContentRefNode extends BlockSpacing {
|
|
169
310
|
type: "content-ref"
|
|
170
311
|
url: string
|
|
171
312
|
children: Inline[]
|
|
313
|
+
/** The block as written when it isn't the canonical `{% content-ref %}` (a `{% file %}` tag), reused while it still says the same. */
|
|
314
|
+
raw?: string
|
|
172
315
|
}
|
|
173
316
|
|
|
174
317
|
export type SourceReferenceKind = "component" | "story"
|
|
@@ -177,7 +320,7 @@ export type SourceReferenceKind = "component" | "story"
|
|
|
177
320
|
* A reference to an export in a real source file. The source file remains the
|
|
178
321
|
* authority; Markdown only stores the composition and presentation metadata.
|
|
179
322
|
*/
|
|
180
|
-
export interface SourceRefNode {
|
|
323
|
+
export interface SourceRefNode extends BlockSpacing {
|
|
181
324
|
type: "source-ref"
|
|
182
325
|
/** Name of the directory mounted by the Docstream Vite plugin. */
|
|
183
326
|
mount: string
|
|
@@ -187,6 +330,8 @@ export interface SourceRefNode {
|
|
|
187
330
|
exportName: string
|
|
188
331
|
kind: SourceReferenceKind
|
|
189
332
|
title?: string
|
|
333
|
+
/** The tag as written (`{% component … %}`, an end tag), reused while it still says the same. */
|
|
334
|
+
raw?: string
|
|
190
335
|
}
|
|
191
336
|
|
|
192
337
|
export type DemoLayout = "auto" | "single" | "multi"
|
|
@@ -222,7 +367,7 @@ export interface DemoInlineFile {
|
|
|
222
367
|
* ```
|
|
223
368
|
* {% enddemo %}
|
|
224
369
|
*/
|
|
225
|
-
export interface DemoNode {
|
|
370
|
+
export interface DemoNode extends BlockSpacing, RawSource {
|
|
226
371
|
type: "demo"
|
|
227
372
|
/** `<page>/<example>` folder id understood by the host's resolver. */
|
|
228
373
|
src: string
|
|
@@ -260,66 +405,103 @@ export interface DemoNode {
|
|
|
260
405
|
open?: true
|
|
261
406
|
}
|
|
262
407
|
|
|
263
|
-
export interface ColumnNode {
|
|
408
|
+
export interface ColumnNode extends ContainerSpacing, TagLines {
|
|
264
409
|
type: "column"
|
|
265
410
|
children: Block[]
|
|
266
411
|
}
|
|
267
412
|
|
|
268
|
-
export interface ColumnsNode {
|
|
413
|
+
export interface ColumnsNode extends ContainerSpacing, TagLines {
|
|
269
414
|
type: "columns"
|
|
270
415
|
columns: ColumnNode[]
|
|
271
416
|
}
|
|
272
417
|
|
|
273
|
-
export interface FigureNode {
|
|
418
|
+
export interface FigureNode extends BlockSpacing {
|
|
274
419
|
type: "figure"
|
|
275
420
|
src: string
|
|
276
421
|
alt: string
|
|
277
422
|
caption: string
|
|
423
|
+
/** ``'s title. */
|
|
424
|
+
title?: string
|
|
425
|
+
/**
|
|
426
|
+
* The line(s) as written (``, `<img …>`, `<figure>…</figure>`). Serialization reuses them while
|
|
427
|
+
* they still parse to the same src / alt / caption / title; otherwise it writes a `<figure>`.
|
|
428
|
+
*/
|
|
429
|
+
raw?: string
|
|
278
430
|
}
|
|
279
431
|
|
|
280
|
-
export interface ListItemNode {
|
|
432
|
+
export interface ListItemNode extends ContainerSpacing {
|
|
281
433
|
type: "listItem"
|
|
282
434
|
children: Block[]
|
|
283
435
|
checked?: boolean // present only in task lists
|
|
436
|
+
/** The item's marker as written (`*`, `3.`), when it isn't the one its list's pattern gives it. */
|
|
437
|
+
marker?: string
|
|
438
|
+
/** Spaces between the marker and the content (default 1). */
|
|
439
|
+
pad?: number
|
|
440
|
+
/** Indent of the item's continuation lines, relative to its marker (default 2). */
|
|
441
|
+
indent?: number
|
|
442
|
+
/** A checked task written `[X]`. */
|
|
443
|
+
checkMark?: "X"
|
|
284
444
|
}
|
|
285
445
|
|
|
286
|
-
export interface ListNode {
|
|
446
|
+
export interface ListNode extends BlockSpacing {
|
|
287
447
|
type: "list"
|
|
288
448
|
ordered: boolean
|
|
289
449
|
task: boolean
|
|
290
450
|
items: ListItemNode[]
|
|
451
|
+
/** Bullet marker of an unordered list (default `-`). */
|
|
452
|
+
bullet?: "*" | "+"
|
|
453
|
+
/** Number of an ordered list's first item (default 1). */
|
|
454
|
+
start?: number
|
|
455
|
+
/** Ordered-list delimiter (default `.`). */
|
|
456
|
+
delimiter?: ")"
|
|
457
|
+
/** Whitespace before the list's markers, as written. */
|
|
458
|
+
indent?: string
|
|
291
459
|
}
|
|
292
460
|
|
|
293
|
-
export interface BlockquoteNode {
|
|
461
|
+
export interface BlockquoteNode extends ContainerSpacing {
|
|
294
462
|
type: "blockquote"
|
|
295
463
|
children: Block[]
|
|
464
|
+
/** Each line's `>` prefix as written (indent, spacing), when not `> ` (`>` on empty lines). */
|
|
465
|
+
markers?: string[]
|
|
296
466
|
}
|
|
297
467
|
|
|
298
|
-
export interface DividerNode {
|
|
468
|
+
export interface DividerNode extends BlockSpacing {
|
|
299
469
|
type: "divider"
|
|
470
|
+
/** The rule as written when not `---` (`***`, `___`, `-----`). */
|
|
471
|
+
marker?: string
|
|
300
472
|
}
|
|
301
473
|
|
|
302
|
-
export interface TableNode {
|
|
474
|
+
export interface TableNode extends BlockSpacing {
|
|
303
475
|
type: "table"
|
|
304
476
|
header: Inline[][]
|
|
305
477
|
rows: Inline[][][]
|
|
306
478
|
/** GitBook table view, e.g. "cards" for <table data-view="cards"> */
|
|
307
479
|
view?: string
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
480
|
+
/** Written as an HTML `<table>` (without a view). */
|
|
481
|
+
html?: true
|
|
482
|
+
/** Column alignment from the delimiter row (`:---`, `:---:`, `---:`); null = default. */
|
|
483
|
+
align?: Array<"left" | "center" | "right" | null>
|
|
484
|
+
/** The delimiter row as written (`|:--|--:|`), reused while it still says the same `align`. */
|
|
485
|
+
delimiterRow?: string
|
|
486
|
+
/** An HTML table as written, reused while it still parses to the same cells. */
|
|
487
|
+
raw?: string
|
|
488
|
+
/** GFM rows as written (header first), each reused while it still parses to the same cells. */
|
|
489
|
+
rawRows?: string[]
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
export interface UpdateNode extends ContainerSpacing, TagLines {
|
|
311
493
|
type: "update"
|
|
312
494
|
date: string
|
|
313
495
|
children: Block[]
|
|
314
496
|
}
|
|
315
497
|
|
|
316
|
-
export interface UpdatesNode {
|
|
498
|
+
export interface UpdatesNode extends ContainerSpacing, TagLines {
|
|
317
499
|
type: "updates"
|
|
318
500
|
format: string | null
|
|
319
501
|
updates: UpdateNode[]
|
|
320
502
|
}
|
|
321
503
|
|
|
322
|
-
export interface OpenApiOperationNode {
|
|
504
|
+
export interface OpenApiOperationNode extends BlockSpacing, RawSource {
|
|
323
505
|
type: "openapi-operation"
|
|
324
506
|
spec: string
|
|
325
507
|
path: string
|
|
@@ -328,7 +510,30 @@ export interface OpenApiOperationNode {
|
|
|
328
510
|
label: string
|
|
329
511
|
}
|
|
330
512
|
|
|
331
|
-
|
|
513
|
+
/**
|
|
514
|
+
* A reference-style link definition, `[label]: url "title"`, where the source put it. Links written
|
|
515
|
+
* `[text][label]`, `[text][]` or `[label]` resolve through it.
|
|
516
|
+
*/
|
|
517
|
+
export interface DefinitionNode extends BlockSpacing {
|
|
518
|
+
type: "definition"
|
|
519
|
+
/** The label as written (matched case-insensitively). */
|
|
520
|
+
label: string
|
|
521
|
+
url: string
|
|
522
|
+
title?: string
|
|
523
|
+
/** The line as written, reused while it still says the same label / url / title. */
|
|
524
|
+
raw?: string
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
/**
|
|
528
|
+
* A line docstream keeps verbatim but doesn't model — an unknown `{% tag %}` (GitBook tags from other
|
|
529
|
+
* integrations). Renders nothing; serialized as written.
|
|
530
|
+
*/
|
|
531
|
+
export interface RawNode extends BlockSpacing {
|
|
532
|
+
type: "raw"
|
|
533
|
+
markdown: string
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
export interface MathNode extends BlockSpacing, RawSource {
|
|
332
537
|
type: "math"
|
|
333
538
|
formula: string
|
|
334
539
|
}
|
|
@@ -355,12 +560,20 @@ export type Block =
|
|
|
355
560
|
| MathNode
|
|
356
561
|
| UpdatesNode
|
|
357
562
|
| OpenApiOperationNode
|
|
563
|
+
| DefinitionNode
|
|
564
|
+
| RawNode
|
|
358
565
|
|
|
359
566
|
export interface DocumentNode {
|
|
360
567
|
type: "doc"
|
|
361
568
|
children: Block[]
|
|
362
569
|
/** Footnote citation definitions, in definition order. */
|
|
363
570
|
citations?: CitationDef[]
|
|
571
|
+
/** Blank lines before the trailing footnote definitions (default 1). */
|
|
572
|
+
citationsGap?: number
|
|
573
|
+
/** Line ending of the source when it used `\r\n` throughout. */
|
|
574
|
+
lineEnding?: "\r\n"
|
|
575
|
+
/** What the source ended with after its last line, when more than a single newline (`"\n\n"`). */
|
|
576
|
+
end?: string
|
|
364
577
|
}
|
|
365
578
|
|
|
366
579
|
export const text = (t: string, marks: Partial<Omit<TextNode, "type" | "text">> = {}): TextNode => ({
|
package/src/gitbook/index.ts
CHANGED
|
@@ -4,7 +4,7 @@ export type * from "./ast"
|
|
|
4
4
|
export { escapeAttr, unescapeAttr } from "./attrs"
|
|
5
5
|
export { closesFence, demoBody, fenceOpener, fenceTracker, parseDemoVariants, parseMarkdown, parseBlocks, trimPartialInlineToken } from "./parse"
|
|
6
6
|
export { fenceFor, serializeBlocks, serializeDemoFile, serializeMarkdown } from "./serialize"
|
|
7
|
-
export { footnoteDefinitions, parseInline, plainText, refDefinitions, serializeInline, serializeReference } from "./inline"
|
|
7
|
+
export { defaultInlineDelims, footnoteDefinitions, inlineDelims, parseInline, plainText, refDefinitions, serializeInline, serializeReference } from "./inline"
|
|
8
8
|
export { PACKAGE_MANAGERS, packageManagerCommands } from "./package-managers"
|
|
9
9
|
export { flattenBlocks, flattenForPlainMarkdown } from "./flatten"
|
|
10
10
|
export { documentOutline, slugify } from "./outline"
|